
import xml.etree.ElementTree as ET
from typing import Dict, List

def xml_to_proto(xml_file: str, output_file: str):
    """
    将XML文件转换为proto定义
    :param xml_file: 输入的XML文件路径
    :param output_file: 输出的.proto文件路径
    """
    tree = ET.parse(xml_file)
    root = tree.getroot()
    
    messages = {}
    _analyze_element(root, messages)
    
    with open(output_file, 'w', encoding='utf-8') as f:
        f.write('syntax = "proto3";\n\n')
        for message_name, fields in messages.items():
            f.write(f'message {message_name} {{\n')
            for i, (field_type, field_name) in enumerate(fields, 1):
                f.write(f'  {field_type} {field_name} = {i};\n')
            f.write('}\n\n')

def _analyze_element(element: ET.Element, messages: Dict, parent_name: str = None) -> str:
    """递归分析XML元素"""
    element_name = element.tag
    if parent_name:
        # message_name = f"{parent_name}_{element_name}"
        message_name = f"{element_name}"
    else:
        message_name = element_name.capitalize()
    
    fields = []
    
    # 处理属性
    for attr_name, attr_value in element.attrib.items():
        field_type = _determine_type(attr_value)
        fields.append((field_type, attr_name))
    
    # 处理子元素
    for child in element:
        if len(child) == 0 and not child.attrib:  # 简单子元素
            field_type = _determine_type(child.text) if child.text else "string"
            fields.append((field_type, child.tag))
        else:  # 复杂子元素
            child_message_name = _analyze_element(child, messages, message_name)
            fields.append((child_message_name, child.tag))
    
    messages[message_name] = fields
    return message_name

def _determine_type(value: str) -> str:
    """根据值确定proto类型"""
    if value is None:
        return "string"
    if value.lower() in ('true', 'false'):
        return "bool"
    try:
        int(value)
        return "int32"
    except ValueError:
        try:
            float(value)
            return "double"
        except ValueError:
            return "string"

if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print("Usage: python xml_to_proto.py input.xml output.proto")
        sys.exit(1)
    
    xml_to_proto(sys.argv[1], sys.argv[2])
    print(f"Proto file generated: {sys.argv[2]}")
